package cn.donting.web.desktop.core.app;

import cn.donting.web.desktop.core.Application;
import cn.donting.web.desktop.core.dao.AppInfoRepository;
import cn.donting.web.desktop.core.dao.OpenFileRepository;
import cn.donting.web.desktop.core.dao.SysSettingRepository;
import cn.donting.web.desktop.core.entity.AppInfo;
import cn.donting.web.desktop.core.entity.OpenFile;
import cn.donting.web.desktop.core.entity.SysSetting;
import cn.donting.web.desktop.core.exception.AppException;
import cn.donting.web.desktop.core.listener.AppListener;
import cn.donting.web.desktop.core.loader.AppLoader;
import cn.donting.web.desktop.top.AppType;
import cn.donting.web.desktop.top.file.FileOpen;
import cn.donting.web.desktop.top.file.FileRegister;
import cn.hutool.core.io.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.EventListener;
import java.util.HashSet;
import java.util.List;
import java.util.UUID;

/**
 * 文件系统管理
 * @author donting
 * 2021-06-12 下午2:30
 */
@Service
@Slf4j
public class FileSysManger implements AppListener {

    public static final String WAP = "wap";
    public static final String DEFAULT_FILE_RESOURCES_ID = "DEFAULT_FILE_RESOURCES_ID";

    public static final String FILE_ICON_PATH = AppManager.SYS_PATH + File.separator + "fileIcon";
    @Autowired
    SysSettingRepository sysSettingRepository;
    @Autowired
    AppInfoRepository appInfoRepository;

    @Autowired
    @Qualifier("appManager")
    AppManager appManager;

    @Autowired
    OpenFileRepository openFileRepository;

    /**
     * 安装出发的事件
     * @param appInfo
     */
    @Override
    public void install(AppInfo appInfo) {
        File file = AppManager.appFile(appInfo);
        AppLoader appLoader = appManager.getAppLoader(file);
        try {
            //启动类是否实现FileRegister
            //是注册 FileOpen
            Application loader = appLoader.loader(file,appInfo);
            Class<?> mainClass = loader.getMainClass();
            Object o = mainClass.newInstance();
            if (o instanceof FileRegister) {
                FileOpen[] register = ((FileRegister) o).register();
                saveOpenFile(register, loader.getAppClassLoader(), appInfo);
            }
        } catch (Exception ex) {
            log.error(appInfo.toString() + " FileRegister 失败");
            log.error(ex.getMessage(), ex);
        }

        //是资源管理器 设为默认
        if (appInfo.getType() == AppType.FileResources) {
            //不存在默认则设置为默认
            SysSetting defaultFileResources = sysSettingRepository.findByKey(DEFAULT_FILE_RESOURCES_ID);
            if (defaultFileResources == null) {
                defaultFileResources = new SysSetting();
                defaultFileResources.setValue(appInfo.getAppId() + "");
                sysSettingRepository.save(defaultFileResources);
            }

        }


    }


    @Override
    public void uninstall(AppInfo appInfo) {
        List<OpenFile> openFiles = openFileRepository.findByAppId(appInfo.getAppId());
        //删除注册的 文件icon
        for (OpenFile openFile : openFiles) {
            File file = new File(FILE_ICON_PATH + File.separator + openFile.getFileName());
            if (file.exists()) {
                file.delete();
            }
        }
        //检查是否是默认 的资源管理器
        if (appInfo.getType() == AppType.FileResources) {
            //获取默认的资源滚离去
            //如果 app 是 FileResources，则一定存在 defaultFileResources
            SysSetting defaultFileResources = sysSettingRepository.findByKey(DEFAULT_FILE_RESOURCES_ID);
            if (defaultFileResources.getValue().equals(appInfo.getAppId()+"")) {
                //获取一个FileResources 设置为默认
                AppInfo firstByType = appInfoRepository.findFirstByType(AppType.FileResources);
                if(firstByType!=null){
                    defaultFileResources.setValue(firstByType.getAppId()+"");
                    sysSettingRepository.save(defaultFileResources);
                }
                sysSettingRepository.deleteById(defaultFileResources.getId());
            }
        }
        //删除记录
        int count = openFileRepository.deleteByAppId(appInfo.getAppId());
        log.debug("openFileRepository.deleteByAppId:" + count);
    }

    /**
     * 初始化，第一次运行 注册
     * 默认的文件图标
     * 未知文件图标
     * wap
     * @throws Exception
     * @see //cn.donting.web.desktop.sys.controller.FileController
     */
    @Override
    public void init() throws Exception {
        File file = new File(FILE_ICON_PATH);
        file.mkdirs();
        FileOpen unknown = new FileOpen(FileOpen.unknown, "icon/unknown.png", "/sys/file/open/unknown");
        FileOpen directory = new FileOpen(FileOpen.directory, "icon/文件夹.png", "/sys/file/open/unknown");
        FileOpen wap = new FileOpen("wap", null, "/sys/file/open/wap");
        saveOpenFile(new FileOpen[]{unknown,wap, directory}, this.getClass().getClassLoader(), AppInfo.sys());
    }

    public OpenFile getOpenFIle(File file) {
        if (!file.exists()) {
            log.warn("文件不存在:[{}]", file.getPath());
            return null;
        }
        String extName;
        if (file.isDirectory()) {
            extName = FileOpen.directory;
        } else {
            //无扩展 会返回 “”
            //目录返回 null
            extName = FileUtil.extName(file);
        }
        OpenFile openFile;
        if (extName == null) {
            openFile = openFileRepository.findByExtNameIsNullAndDefaultValue(true);
        } else {
            openFile = openFileRepository.findByExtNameAndDefaultValue(extName, true);
        }
        if (openFile == null) {
            if (extName == null) {
                openFile = openFileRepository.findFirstByExtNameIsNull();
            } else {
                openFile = openFileRepository.findFirstByExtName(extName);
            }
        }
        return openFile;
    }


    private synchronized void saveOpenFile(FileOpen[] fileOpens, ClassLoader classLoader, AppInfo appInfo) throws Exception {
        HashSet<String> hashSet = new HashSet<>();
        try {

            for (FileOpen fileOpen : fileOpens) {
                if (hashSet.contains(fileOpen.getExtName())) {
                    log.info("{}重复：", fileOpen.getExtName());
                    continue;
                }
                hashSet.add(fileOpen.getExtName());
                if (WAP.equals(fileOpen.getExtName()) && !appInfo.getAppId().equals(Application.sysAppId)) {
                    log.warn(appInfo.toString() + "尝试注册 wap");
                    continue;
                }
                //写入 db
                OpenFile openFile = new OpenFile();
                openFile.setAppId(appInfo.getAppId());
                openFile.setExtName(fileOpen.getExtName());
                openFile.setIcon(fileOpen.getIcon());
                openFile.setOpenFileUrl(fileOpen.getOpenFileUrl());
                //没有默认设为默认
                OpenFile defaultValue = openFileRepository.findByExtNameAndDefaultValue(fileOpen.getExtName(), true);
                if (defaultValue == null) {
                    openFile.setDefaultValue(true);
                }
                if (fileOpen.getIcon() != null) {
                    //复制icon 到 sys/fileIcon
                    URL resource = classLoader.getResource(fileOpen.getIcon());
                    if (resource == null) {
                        if (fileOpen.getIcon().startsWith("/")) {
                            log.warn("classLoader.getResource()  请不要使用 / 开头");
                        }
                        throw new AppException(fileOpen.getIcon() + " not found");
                    }
                    File targetFile = new File(FILE_ICON_PATH + File.separator + UUID.randomUUID().toString() + "." + FileUtil.extName(resource.getFile()));
                    targetFile.createNewFile();
                    cn.donting.web.desktop.core.unilt.FileUtil.copy(targetFile, resource);
                    openFile.setFileName(targetFile.getName());
                }
                openFileRepository.save(openFile);
            }
        } catch (Exception ex) {
            log.error(appInfo.toString() + " FileRegister 失败");
            log.error(ex.getMessage(), ex);
            throw ex;
        }


    }
}
